雖然說網格線會隨著網格項目自動生成,但既然要使用網格系統,就要了解怎麼操控網格線,才能劃出各種多變的網格區域,然而畫網格線有很多種做法,且每種做法的語法也不同,怎麼利用 grid-template (網格樣板) 使用得當是一個難題。(本篇筆記較長約7000字,慎閱)
.container {
grid-template:
none |
[<grid-template-rows> / <grid-template-columns>] |
[ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?;
}
預設:none
.container {
grid-template-rows: none | <track-list> | <auto-track-list> ;
grid-template-columns: 同上 ;
grid-template: <grid-template-rows> / <grid-template-columns>
grid: <grid-template-rows> / <grid-template-columns>
}
預設:none
英文小幫手:
grid-template
網格樣板track-list
軌道列表
由於樣板中的軌道列表操縱方法非常多,雖然複雜但也增加了創造網格系統的彈性,想看有哪些的可以見The syntax of a track list,下面也會陸續介紹常用的網格線放置用法:
1.基本固定網格
2.minmax()
最小值與最大值
3.fr
份數
4.max-content/min-content
最小內容尺寸/最大內容尺寸
5.fit-content
貼合內容尺寸
6.repeat()
重複網格線及間距
7.auto-fill/autofit
自動重複網格線(自動填滿網格軌道)
網格內要放置幾條線?容器要分成幾等份?線和線之間的尺寸又是多少呢?我們將使用 grid-template-rows/grid-template-columns 放置網格線來解決以上的問題
首先要注意的是,定義網格線不等同於定義網格容器的大小,定義網格線是有機會不足或超出網格容器的;且在使用百分比時,計算尺寸會以網格容器的尺寸為目標來做計算,所以在樣板中寫 100% 就代表著那塊網格單元格要佔據網格容器的總寬/長。
a. 定義網格線間距
.container {
grid-template-columns: 50px 50% 100px;
grid-template-rows: 50px 100px 50px;
}
(淺藍色區域為網格容器,虛線內為網格格式環境)
b. 命名網格線:利用中括號
自訂義,命名多個名稱則用空白做間隔([名稱 名稱 名稱 ....]
),網格線間隔的數字即線段間距;行與列有自己的命名空間,所以可以取一樣的名字。
.container {
grid-template-columns:
[start col-a] 50px [col-b] 50% [col-c] 100px [stop end last];
grid-template-rows:
[start header] 50px [content] 100px [footer] 50px [stop end];
}
minmax()
比大小另一個較為彈性的語法 minmax()
,直接定義最小值和最大值,如果不小心把較大的數值寫在前面,就會取其後面為最小的值做為固定長度。
.container {
grid-template-columns:
[start col-a] 50px [col-b] minmax(50px,100%) [col-c] 100px [stop end last];
grid-template-rows:
[start header] 50px [content] 100px [footer] 50px [stop end];
}
如果網格項目的總內容尺寸超出網格容器,網格項目直接突破容器是正常的。
如果對於 minmax()
的值感到難以預判,可以利用 calc()
來做計算,假設要讓網格占滿螢幕高度,可以使用 calc(100% - 其他的尺寸)
。
然而只要 header
或 footer
的數值需要變化,calc() 的數值就得做調整。另外,只要不是長度單位的都不能在 calc()
表達式中使用,這意味著它不能在()裡面放 fr
,因為 fr
不是長度單位,不過在 minmax()
是可以的。
fr
分配單位如果想要讓網格單位變得有彈性,或許會想到可以使用 %
,不過這邊有個新的比例分配單位 fr
可以做到更好的彈性。
fr
:fraction
,中文意思是分數,當使用在網格軌道上時,可以直接想像成 "我的這個空位要佔有總 fr
數量的幾等份"。
假設我的網格軌道要分成4等份:
.container {
grid-template-columns: 1fr 1fr 1fr 1fr;
/*等同於*/
grid-template-columns: 25% 25% 25% 25%;
}
然而當我想任意修改等份時,使用 fr
只要知道 fr
要等份成幾塊即可,但使用 %
卻得再重新做計算。
.container {
grid-template-columns: 2fr 3fr 1fr 1fr 3fr;
/* 等同於 */
grid-template-columns: 20% 25% 15% 15% 25%;
}
當然你還是可以和其他的單位混用。另外如果螢幕寬度縮小,沒有剩餘空間,就沒有足夠位置給 fr
,就不會有 fr
這個位置。下面的例子如果網格寬度沒有超出700px,就不會有 1fr 這個空間出現;當網格寬度只有200px時,連 minmax(0,500px) 都不會出現(因為已經縮為0px)。
.container {
grid-template-columns: 100px 1fr minmax(0, 500px) 100px
}
除此之外 fr
也可以使用小數點。
.container {
grid-template-columns: 1fr 3.1415986fr 1fr
}
這種複雜的數學運算還是留給電腦吧。
max-content
/ min-content
依內容而變如果需要不固定的網格內容(如共用模板),或是不確內容需要多少空間,這時可以使用 min-content
和 max-content
。
max-content
:給予網格區域所需的最大尺寸空間,內容盡可能避免折行。
min-content
:給予網格區域所需的最小尺寸空間,內容盡可能的折行,但不會溢出邊界。
.container {
grid-template-columns: max-content max-content max-content;
grid-template-rows: max-content max-content max-content;
}
這樣的方式雖然所有的內容都會以不折行的方式,以最大尺寸來呈現在網格軌道中,這意味著如果內容尺寸超過網格容器,便會突破便網格容器。
minmax()
+fr
a. minmax() 和 fr 共用可以達到很好的 RWD 展現。
.container {
grid-template-columns: minmax(100px, 200px) 1fr 1fr;
}
b. 把 fr 寫在 minmax() 裡面,想要設定最小寬度和彈性尺寸的佔位時可以使用這種方法。
.container {
grid-template-rows: 3em minmax(5em, 1fr) 2em
}
minmax()
+min-content
/max-content
a. minmax( 0, max-content )
最小為 0(當然也可以換其他數字來放最小值),網格區域如果沒有內容就會沒有尺寸;然而在這裡最大值使用 max-content ,當內容超出網格單元格時,內容會突破網格項目區域,而可能覆蓋在下一個網格項目之下。
.container {
grid-template-colmns: 3em minmax(0, max-content) 2em
}
b. minmax( min-content, max-content )
縮到最小時會是內容可接受的最小尺寸,如果總內容超出容器還是會突破容器;拉到最大時會是內容最大尺寸,甚至會超出容器。
.container {
grid-template-rows: 3em minmax(min-content, max-content) 2em
}
c. minmax( min-content, 數字 )
.container {
grid-template-rows: 3em minmax(min-content, 500px) 2em
}
縮到最小時會是內容可接受的最小尺寸,如果總內容超出項目還是會突破容器;尺寸放大後最大就會是所設定的尺寸。
minmax()
+min-content
/max-content
+fr
如果用得恰到好處,可以展現 RWD,不會有內容的溢出問題,且網格項目最大只會到內容的寬度
.container {
grid-template-columns: minmax(min-content, max-content) 1fr 1fr;
}
fit-content
貼合內容文件:
fit-content(argument) = min(max-content, max(min-content, argument))
引數 (argument
) 可以是長度單位或是百分比
就表面上翻譯來說是「先比較內容最小尺寸和引數(argument)之間誰最大,再比較內容最大尺寸和上一個勝出的誰最大」,一定很難懂吧。
可以直接把 fit-content()
當作 minmax(min-content, max-content)
,當引數或超過引數尺寸的內容會作為內容尺寸的最大值 max-content,而網格區域又可以縮到內容的極限小 min-content,這樣比較好理解。
.container {
grid-template-columns: fit-content(50px) 1fr 1fr;
}
/* 上面這個 fit-content 的最大寬度就是50px,最小寬度就是內容的極限小 */
repeat()
重複的網格線如果遇到一再出現且相同尺寸的網格,可以利用 repeat()
來簡化程式碼。
.container{
grid-template-columns: repeat(6, 1em 1fr);
}
前面第一個數代表重複次數,後面的代表要重複的間距,上面這個例子可以做到重複6次 1em 1fr的軌道模式。
repeat()
可以和其他尺寸軌道混合使用,甚至可以寫多個 repeat()
,但不能使用巢狀寫法。(上面這個例子在最右邊加個 1em
可以讓畫面更平衡)
.container{
grid-template-columns: repeat(6, 1em 1fr) 1em;
}
命名網格線也可以重複,甚至同時有兩個名稱,重複的名稱在某些情況下十分有用
.container{
grid-template-columns: repeat(4, 10px [col-start] 250px [col-end]) 10px;
}
.container{
grid-template-columns: repeat(3, [top] 5em [bottom]);
}
/* 等同於 */
.container{
grid-template-columns: [top] 5em [bottom top] 5em [top bottom] 5em [bottom];
}
auto-fill
/ auto-fit
自動重複網格線(自動填滿軌道)在使用 repeat()
時,如果不確定自己要的重複次數,可以使用 auto-fill
和 autofit
讓重複的網格持續填滿。
auto-fill
:自動填滿重複的軌道.container{
grid-template-columns: repeat(auto-fill, [top] 60px [bottom]);
}
這樣網格容器就會每 60px
就多一條網格線,而剩下多出的會自占一格。
然而 auto-fill
有所限制,最多只能重複「兩條名稱線 + 中間一個固定尺寸單位」,頂多也只能少其中一條名稱線,只要不符合將無法重複。當然也不能同時宣告兩個或以上的 auto-fill
。
auto-fit
:自動填滿重複的軌道,網格單元格內如果沒有彈性項目,那個網格單元格就會被折疊起來,尺寸變為0px。(後續會有可以指定彈性項目在網格的位置,則其他沒有放彈性項目的網格區域就會變為 0px).container{
grid-template-columns: repeat(auto-fit, [top] 60px [bottom]);
}
資料來源: